package com.pt5.pthouduan.service.impl;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.pt5.pthouduan.entity.*;
import com.pt5.pthouduan.exception.TorrentNotFoundException;
import com.pt5.pthouduan.mapper.*;
import com.pt5.pthouduan.service.TorrentService;
import com.pt5.pthouduan.util.TorrentParser;
import com.turn.ttorrent.bcodec.BDecoder;
import com.turn.ttorrent.bcodec.BEValue;
import com.turn.ttorrent.bcodec.BEncoder;
import com.turn.ttorrent.tracker.TrackedTorrent;
import com.turn.ttorrent.tracker.Tracker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class TorrentServiceImpl implements TorrentService {

    @Value("${tracker.url}")  //等等看看这个有没有传进来
    private String trackerUrl;
    @Autowired
    private TorrentMapper torrentMapper;
    @Autowired  // 确保使用接口类型（推荐）
    private Tracker tracker;
    @Autowired
    private MovieInfoMapper movieInfoMapper;
    // 🎵 Music 音乐
    @Autowired
    private MusicInfoMapper musicInfoMapper;

    // 🎮 Game 游戏
    @Autowired
    private GameInfoMapper gameInfoMapper;

    // 📺 TV 剧集
    @Autowired
    private TvInfoMapper tvInfoMapper;

    // 🧸 Anime 动漫
    @Autowired
    private AnimeInfoMapper animeInfoMapper;

    // 📚 Learning 学习
    @Autowired
    private EduInfoMapper eduInfoMapper;

    // � Software 软件
    @Autowired
    private SoftwareInfoMapper softwareInfoMapper;

    // 🎤 Variety 综艺
    @Autowired
    private ShowInfoMapper showInfoMapper;

    // ⚽ Sports 体育
    @Autowired
    private SportInfoMapper sportInfoMapper;

    // 🎬 Documentary 纪录片
    @Autowired
    private DocumentaryInfoMapper documentaryInfoMapper;

    // 📦 Other 其他
    @Autowired
    private OtherInfoMapper otherInfoMapper;


    public List<Torrent> getAllTorrents() {
        return torrentMapper.getAllTorrents();
    }
    public List<Torrent> getTorrentsByCategory(Integer category) {
        return torrentMapper.selectTorrentsByCategory(category);
    }
    public Torrent getTorrentById(Long id) {
        return torrentMapper.selectById(id);
    }



//    @Override
//    public void Upload(MultipartFile torrentFile, String title, String description, User user) throws Exception {
//        //读取torrent文件
//        InputStream inputStream = torrentFile.getInputStream();
//        //解析torrent文件
//        byte[] torrentData = torrentFile.getBytes();
//        Torrent torrent = TorrentParser.parse(torrentData);
//        //验证info_hash是否存在
//        Integer result;
//        result = torrentMapper.existsByInfoHash(torrent.getInfoHash());
//        if(result >= 1){
//            throw new IllegalArgumentException("Torrent already exists");
//        }
//        String fileSavePath = "D:/torrenttest/" + torrentFile.getOriginalFilename();
//        torrentFile.transferTo(new File(fileSavePath));
//        // 4. 注册到Tracker（关键步骤！）
//        TrackedTorrent trackedTorrent = TrackedTorrent.load(new File(fileSavePath));
//        tracker.announce(trackedTorrent);
//        //存入数据库
//        Torrent entity = new Torrent();
//        entity.setInfoHash(torrent.getInfoHash());
//        entity.setUploader_id(user.getUserid());
//        entity.setTorrentTitle(title);
//        entity.setDescription(description);
//        entity.setTorrentSize(torrent.getTorrentSize());
//        entity.setFilename(torrentFile.getOriginalFilename());
//        entity.setPath(fileSavePath); // 保存路径到数据库
//        torrentMapper.save(entity);
//    }
@Override
public ResponseEntity<Resource> Upload(MultipartFile torrentFile, String title, String description, Integer categoryId, String dpi, String caption,User user) throws Exception {
    //读取torrent文件
    InputStream inputStream = torrentFile.getInputStream();
    // === 1. 基础校验 ===
    if (torrentFile.isEmpty()) {
        throw new IllegalArgumentException("Torrent file cannot be empty");
    }
    // === 2. 注入passkey ===
    byte[] modifiedData = addPasskeyToTorrent(torrentFile.getBytes(), "111111");
    Torrent torrent = TorrentParser.parse(modifiedData);
    // === 4. 检查重复 ===
    if (torrentMapper.existsByInfoHash(torrent.getInfoHash()) >= 1) {
        throw new IllegalArgumentException("Torrent already exists");
    }
    String fileSavePath = "D:/torrenttest/" + torrentFile.getOriginalFilename();
    //torrentFile.transferTo(new File(fileSavePath));
    Files.write(new File(fileSavePath).toPath(), modifiedData);
    // 4. 注册到Tracker（关键步骤！）
    TrackedTorrent trackedTorrent = TrackedTorrent.load(new File(fileSavePath));
    tracker.announce(trackedTorrent);
    //存入数据库
    Torrent entity = new Torrent();
    entity.setInfoHash(torrent.getInfoHash());
    entity.setUploader_id(user.getUserid());
    entity.setTorrentTitle(title);
    entity.setDescription(description);
    entity.setTorrentSize(torrent.getTorrentSize());
    entity.setFilename(torrentFile.getOriginalFilename());
    entity.setCategoryid(categoryId);
    entity.setCaption(caption);
    entity.setDpi(dpi);
    entity.setUploadTime(LocalDateTime.now());
    entity.setPath(fileSavePath); // 保存路径到数据库
    torrentMapper.save(entity);
    // 返回修改后的.torrent文件给用户下载
    ByteArrayResource resource = new ByteArrayResource(modifiedData);
    // 2. 设置正确的Content-Type
    // 构建响应，下载.torrent文件
    // 构建响应，下载.torrent文件
//    HttpHeaders headers = new HttpHeaders();
//    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//    headers.setContentDisposition(ContentDisposition.attachment()
//            .filename(torrentFile.getOriginalFilename())
//            .build());
//    return new ResponseEntity<>(resource, headers, HttpStatus.OK);
    return ResponseEntity.ok()
            .header(HttpHeaders.CONTENT_DISPOSITION,
                    "attachment; filename=\"" + torrentFile.getOriginalFilename() + "\"")
            .contentType(MediaType.parseMediaType("application/x-bittorrent"))
            .body(new ByteArrayResource(modifiedData));
}
    @Override
    public ResponseEntity<Resource> uploadWithCategory(MultipartFile torrentFile, String title, String description, Integer categoryId, User user, Map<String, String> extraParams ) throws Exception {
        //读取torrent文件
        InputStream inputStream = torrentFile.getInputStream();
        // === 1. 基础校验 ===
        if (torrentFile.isEmpty()) {
            throw new IllegalArgumentException("Torrent file cannot be empty");
        }
        // === 2. 注入passkey ===
        byte[] modifiedData = addPasskeyToTorrent(torrentFile.getBytes(), "111111");
        Torrent torrent = TorrentParser.parse(modifiedData);
        // === 4. 检查重复 ===
        if (torrentMapper.existsByInfoHash(torrent.getInfoHash()) >= 1) {
            throw new IllegalArgumentException("Torrent already exists");
        }
        String fileSavePath = "D:/torrenttest/" + torrentFile.getOriginalFilename();
        //torrentFile.transferTo(new File(fileSavePath));
        Files.write(new File(fileSavePath).toPath(), modifiedData);
        // 4. 注册到Tracker（关键步骤！）
        TrackedTorrent trackedTorrent = TrackedTorrent.load(new File(fileSavePath));
        tracker.announce(trackedTorrent);
        //存入数据库
        Torrent entity = new Torrent();
        entity.setInfoHash(torrent.getInfoHash());
        entity.setUploader_id(user.getUserid());
        entity.setTorrentTitle(title);
        entity.setDescription(description);
        entity.setTorrentSize(torrent.getTorrentSize());
        entity.setFilename(torrentFile.getOriginalFilename());
        entity.setCategoryid(categoryId);
        entity.setUploadTime(LocalDateTime.now());
        entity.setPath(fileSavePath); // 保存路径到数据库
        torrentMapper.save(entity);
        switch (categoryId) {
            case 1: // 🎬 Movie 电影
                MovieInfo movie = new MovieInfo();
                movie.setTorrentid(entity.getTorrentid());
                System.out.println(entity.getTorrentid());
                movie.setRegion(extraParams.get("region"));
                movie.setYear(extraParams.get("year") != null ? Integer.parseInt(extraParams.get("year")) : null);
                movie.setGenre(extraParams.get("genre"));
                movie.setCodecFormat(extraParams.get("codecFormat"));
                movie.setResolution(extraParams.get("resolution"));
                movieInfoMapper.insert(movie);
                break;

            case 3: // 🎵 Music 音乐
                MusicInfo music = new MusicInfo();
                music.setTorrentid(entity.getTorrentid());
                music.setGenre(extraParams.get("genre"));
                music.setRegion(extraParams.get("region"));
                music.setStyle(extraParams.get("style"));
                music.setFormat(extraParams.get("format"));
                musicInfoMapper.insert(music);
                break;

            case 5: // 🎮 Game 游戏
                GameInfo game = new GameInfo();
                game.setTorrentid(entity.getTorrentid());
                game.setPlatform(extraParams.get("platform"));
                game.setGenre(extraParams.get("genre"));
                game.setFormat(extraParams.get("dataType"));
                game.setLanguage(extraParams.get("language"));
                gameInfoMapper.insert(game);
                break;

            case 2: // 📺 TV 剧集
                TvInfo tv = new TvInfo();
                tv.setTorrentId(entity.getTorrentid());
                tv.setRegion(extraParams.get("region"));
                tv.setFormat(extraParams.get("format"));
                tv.setGenre(extraParams.get("genre"));
                tvInfoMapper.insert(tv);
                break;

            case 4: // 🧸 Anime 动漫
                AnimeInfo anime = new AnimeInfo();
                anime.setTorrentid(entity.getTorrentid());
                anime.setGenre(extraParams.get("genre"));
                anime.setFormat(extraParams.get("format"));
                anime.setResolution(extraParams.get("resolution"));
                animeInfoMapper.insert(anime);
                break;

            case 9: // 📚 Learning 学习
                EduInfo learning = new EduInfo();
                learning.setTorrentid(entity.getTorrentid());
                learning.setGenre(extraParams.get("genre"));
                learning.setFormat(extraParams.get("format"));
                eduInfoMapper.insert(learning);
                break;

            case 8: // 🧰 Software 软件
                SoftwareInfo software = new SoftwareInfo();
                software.setTorrentid(entity.getTorrentid());
                software.setPlatform(extraParams.get("platform"));
                software.setGenre(extraParams.get("genre"));
                software.setFormat(extraParams.get("format"));
                softwareInfoMapper.insert(software);
                break;

            case 6: // 🎤 Variety 综艺
                ShowInfo variety = new ShowInfo();
                variety.setTorrentid(entity.getTorrentid());
                variety.setIsMainland(Boolean.valueOf(extraParams.get("mainland")));  // 是否大陆综艺
                variety.setGenre(extraParams.get("genre"));
                variety.setFormat(extraParams.get("format"));
                showInfoMapper.insert(variety);
                break;

            case 7: // ⚽ Sports 体育
                SportInfo sports = new SportInfo();
                sports.setTorrentid(entity.getTorrentid());
                sports.setGenre(extraParams.get("genre"));
                sports.setEventType(extraParams.get("eventType"));
                sports.setFormat(extraParams.get("format"));
                sportInfoMapper.insert(sports);
                break;

            case 10: // 🎬 Documentary 纪录片
                DocumentaryInfo doc = new DocumentaryInfo();
                doc.setTorrentid(entity.getTorrentid());
                doc.setYear(extraParams.get("year") != null ? Integer.parseInt(extraParams.get("year")) : null);
                doc.setSource(extraParams.get("source"));  // 节目源
                doc.setFormat(extraParams.get("format"));
                documentaryInfoMapper.insert(doc);
                break;

            case 11: // 📦 Other 其他
                OtherInfo other = new OtherInfo();
                other.setTorrentid(entity.getTorrentid());
                other.setGenre(extraParams.get("genre"));
                otherInfoMapper.insert(other);
                break;

            default:
                System.out.println("不支持的分类，或无扩展表记录");
        }

        // 返回修改后的.torrent文件给用户下载
        ByteArrayResource resource = new ByteArrayResource(modifiedData);
        // 2. 设置正确的Content-Type
        // 构建响应，下载.torrent文件
        // 构建响应，下载.torrent文件
//    HttpHeaders headers = new HttpHeaders();
//    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//    headers.setContentDisposition(ContentDisposition.attachment()
//            .filename(torrentFile.getOriginalFilename())
//            .build());
//    return new ResponseEntity<>(resource, headers, HttpStatus.OK);
        System.out.println("运行到这里了");
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        "attachment; filename=\"" + torrentFile.getOriginalFilename() + "\"")
                .contentType(MediaType.parseMediaType("application/x-bittorrent"))
                .body(new ByteArrayResource(modifiedData));
    }
    // 专用方法：向torrent文件注入passkey
    private byte[] addPasskeyToTorrent(byte[] originalData, String passkey) throws Exception {
        // 1. 解析原始torrent
        BEValue decoded = BDecoder.bdecode(new ByteArrayInputStream(originalData));
        Map<String, BEValue> torrentMap = decoded.getMap();

        // 2. 修改announce URL
        String originalAnnounce = torrentMap.get("announce").getString();
        String newAnnounce = originalAnnounce.contains("?")
                ? originalAnnounce + "&passkey=" + passkey
                : originalAnnounce + "?passkey=" + passkey;

        // 3. 重建torrent文件
        torrentMap.put("announce", new BEValue(newAnnounce));
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        BEncoder.bencode(torrentMap, baos);
        return baos.toByteArray();
    }

    @Override
    public List<Torrent> getTorrentsByCategorywithfilters(Integer categoryid, Map<String, String> filters) {
        String extendTable = getExtendTableByCategoryId(categoryid);
        if(extendTable == null) {
            System.out.println("未知表");
        }
        return torrentMapper.listByCategoryWithFilters(categoryid,filters,extendTable);
    }

    private String getExtendTableByCategoryId(Integer categoryid) {
        switch(categoryid) {
            case 1:return "movie_info";
            case 2:return "tvseries_info";
            case 3:return "music_info";
            case 4:return "anime_info";
            case 5:return "game_info";
            case 6:return "variety_info";
            case 7:return "sport_info";
            case 8:return "software_info";
            case 9:return "edu_info";
            case 10:return "documentary_info";
            case 11: return "other_info";
        }
        return null;
    }

    //    @Override
//    public Torrent getTorrentFile(Long torrentid) {
//        System.out.println("查询结果：" + torrentid);
//        Torrent result = torrentMapper.selectById(torrentid);
//        if(result != null){
//            System.out.println("not null：" + torrentid);
//        }else{
//            System.out.println("null：" + torrentid);
//        }
//        return torrentMapper.selectById(torrentid);
//    }
@Override
public Torrent getTorrentFile(Long torrentid) {
    System.out.println("查询参数：" + torrentid);
    try {
        Torrent result = torrentMapper.selectById(torrentid);
        System.out.println("第一次查询结果：" + (result != null ? "非空" : "空"));
        return result;
    } catch (Exception e) {
        System.out.println("查询异常：" + e.getMessage());
        e.printStackTrace();
        return null;
    }
}


    @Override
    public Resource loadTorrentFileAsResource(String filepath) throws Exception{
        try{
            Path file = Paths.get(filepath).normalize();
            Resource resource = new UrlResource(file.toUri());

            if(resource.exists() || resource.isReadable()){
                return resource;
            }else{
                throw new Exception("Could not read file: " + filepath);
            }
        }catch(MalformedURLException e){
            throw new Exception("Could not read file: " + filepath,e);
        }
    }

    @Override
    public void incrementDownloadCount(Long torrentid) {
        torrentMapper.incrementDownloadCount(torrentid);
    }
}
